home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / X11 / xpaint-2.1.1 / iprocess.c < prev    next >
C/C++ Source or Header  |  1995-05-03  |  6KB  |  302 lines

  1. /* +-------------------------------------------------------------------+ */
  2. /* | Copyright 1993, David Koblas (koblas@netcom.com)                  | */
  3. /* |                                                                   | */
  4. /* | Permission to use, copy, modify, and to distribute this software  | */
  5. /* | and its documentation for any purpose is hereby granted without   | */
  6. /* | fee, provided that the above copyright notice appear in all       | */
  7. /* | copies and that both that copyright notice and this permission    | */
  8. /* | notice appear in supporting documentation.  There is no           | */
  9. /* | representations about the suitability of this software for        | */
  10. /* | any purpose.  this software is provided "as is" without express   | */
  11. /* | or implied warranty.                                              | */
  12. /* |                                                                   | */
  13. /* +-------------------------------------------------------------------+ */
  14.  
  15. #include <X11/Intrinsic.h>
  16. #include <X11/StringDefs.h>
  17. #include <X11/Xatom.h>
  18. #include <stdio.h>
  19. #include "image.h"
  20.  
  21. /*
  22. **  Some real image processing
  23. */
  24.  
  25. #define CLAMP(low, value, high) \
  26.         if (value < low) value = low; else if (value > high) value = high
  27.  
  28. typedef float    ConvMatrix[3][3];
  29.  
  30. static Image *convolve(Image *input, ConvMatrix mat, 
  31.             unsigned char *basePixel, Boolean absFlag)
  32. {
  33.     int        x,y,xx,yy, xv,yv;
  34.     float        sum;
  35.     unsigned char    *p;
  36.     unsigned char    *op;
  37.     float        r, g, b;
  38.     int        ir, ig, ib;
  39.     Image        *output;
  40.  
  41.     sum = 0;
  42.     for (y = 0; y < 3; y++)
  43.         for (x = 0; x < 3; x++)
  44.             sum += mat[x][y];
  45.     if (sum <= 0)
  46.         sum = 0.5;
  47.  
  48.     output = ImageNew(input->width, input->height);
  49.     op     = output->data;
  50.  
  51.     for (y = 0; y < input->height; y++) {
  52.         for (x = 0; x < input->width; x++) {
  53.             r = g = b = 0;
  54.             sum = 0;
  55.             for (yy = 0; yy < 3; yy++) {
  56.                 for (xx = 0; xx < 3; xx++) {
  57.                     xv = x + xx - 1;
  58.                     yv = y + yy - 1;
  59.                     if (xv < 0 || yv < 0)
  60.                         continue;
  61.                     if (xv >= input->width || yv >= input->height)
  62.                         continue;
  63.                     p = ImagePixel(input, xv, yv);
  64.                     r += (float)p[0] * mat[xx][yy];
  65.                     g += (float)p[1] * mat[xx][yy];
  66.                     b += (float)p[2] * mat[xx][yy];
  67.                     sum += mat[xx][yy];
  68.                 }
  69.             }
  70.             if (sum <= 0)
  71.                 sum = 1;
  72.             if (absFlag) {
  73.                 if (r < 0) r = -r;
  74.                 if (g < 0) g = -g;
  75.                 if (b < 0) b = -b;
  76.             }
  77.             ir = r / sum; 
  78.             if (basePixel) ir += basePixel[0];
  79.             CLAMP(0, ir, 255);
  80.  
  81.             ig = g / sum; 
  82.             if (basePixel) ig += basePixel[1];
  83.             CLAMP(0, ig, 255);
  84.  
  85.             ib = b / sum; 
  86.             if (basePixel) ib += basePixel[2];
  87.             CLAMP(0, ib, 255);
  88.  
  89.             *op++ = ir;
  90.             *op++ = ig;
  91.             *op++ = ib;
  92.         }
  93.  
  94.         if (y % 16 == 0)
  95.             StateTimeStep();
  96.     }
  97.  
  98.     return output;
  99. }
  100.  
  101. /*
  102. **  rescale values from 0..255
  103. */
  104. static void normalize(Image *image)
  105. {
  106.     int        i, count;
  107.     unsigned char    *sp;
  108.     unsigned char    *ip;
  109.     int        v, maxval = 0;
  110.  
  111.     if (image->cmapSize != 0) {
  112.         sp = image->cmapData;
  113.         count = image->cmapSize * 3;
  114.     } else {
  115.         sp = image->data;
  116.         count = image->width * image->height * 3;
  117.     }
  118.  
  119.     for (ip = sp, i = 0; i < count; i++, ip++)
  120.         if (*ip > maxval) 
  121.             maxval = *ip;
  122.     if (maxval == 0)
  123.         return;
  124.     for (ip = sp, i = 0; i < count; i++, ip++) {
  125.         v = ((int)*ip * 255) / maxval;
  126.         CLAMP(0,v,255);
  127.         *ip = v;
  128.     }
  129. }
  130.  
  131. /*
  132. **  Convert image into a monochrome image
  133. */
  134. static void monochrome(Image *image)
  135. {
  136.     int        i, count;
  137.     unsigned char    *sp;
  138.     unsigned char    *ip;
  139.     int        v;
  140.  
  141.     if (image->cmapSize != 0) {
  142.         sp = image->cmapData;
  143.         count = image->cmapSize;
  144.     } else {
  145.         sp = image->data;
  146.         count = image->width * image->height;
  147.     }
  148.  
  149.     for (ip = sp, i = 0; i < count; i++, ip += 3) {
  150.         v = (ip[0]*11 + ip[1]*16 + ip[2]*5) >> 5;  /* pp=.33R+.5G+.17B */
  151.         ip[0] = v;
  152.         ip[1] = v;
  153.         ip[2] = v;
  154.     }
  155. }
  156.  
  157.  
  158. Image *ImageSmooth(Image *input)
  159. {
  160.     static ConvMatrix    mat = {
  161.             { 1, 1, 1 },
  162.             { 1, 1, 1 },
  163.             { 1, 1, 1 }
  164.         };
  165.     return convolve(input, mat, NULL, False);
  166. }
  167.  
  168. Image *ImageSharpen(Image *input)
  169. {
  170.     static ConvMatrix    mat = {
  171.             { -1, -2, -1 },
  172.             { -2, 20, -2 },
  173.             { -1, -2, -1 }
  174.         };
  175.     return convolve(input, mat, NULL, False);
  176. }
  177.  
  178. Image *ImageEdge(Image *input)
  179. {
  180.     static ConvMatrix    mat = {
  181.             { -1, -2,  0 },
  182.             { -2,  0,  2 },
  183.             {  0,  2,  1 }
  184.         };
  185.     Image    *image = convolve(input, mat, NULL, True);
  186.  
  187.     normalize(image);
  188.  
  189.     return image;
  190. }
  191.  
  192. Image *ImageEmbose(Image *input)
  193. {
  194.     static ConvMatrix    mat = {
  195.             { -1, -2,  0 },
  196.             { -2,  0,  2 },
  197.             {  0,  2,  1 }
  198.         };
  199.     static unsigned char    base[3] = { 128, 128, 128 };
  200.     Image    *image = convolve(input, mat, base, False);
  201.  
  202.     monochrome(image);
  203.     normalize(image);
  204.  
  205.     return image;
  206. }
  207.  
  208. Image *ImageInvert(Image *input)
  209. {
  210.     Image        *output = ImageNewCmap(input->width, input->height, input->cmapSize);
  211.     int        i;
  212.     unsigned char    *ip, *op;
  213.     int        count;
  214.     
  215.     /*
  216.     **   If the input has a colormap, just invert that.
  217.     */
  218.     if (input->cmapSize != 0) {
  219.         ip = input->cmapData;
  220.         op = output->cmapData;
  221.         count = input->cmapSize;
  222.  
  223.         memcpy(output->data, input->data, 
  224.             sizeof(char) * input->scale * input->width * input->height);
  225.     } else {
  226.         ip = input->data;
  227.         op = output->data;
  228.         count = input->width * input->height;
  229.     }
  230.  
  231.     for (i = 0; i < count; i++) {
  232.         *op++ = 255 - *ip++;
  233.         *op++ = 255 - *ip++;
  234.         *op++ = 255 - *ip++;
  235.     }
  236.  
  237.     return output;
  238. }
  239.  
  240. #define AREA     7
  241. #define AREA_2    (AREA/2)
  242.  
  243. Image *ImageOilPaint(Image *input)
  244. {
  245.     Image        *output = ImageNew(input->width, input->height);
  246.     unsigned char    *op = output->data;
  247.     int        x, y, xx, yy, i;
  248.     int        rVal, gVal, bVal;
  249.     int        rCnt, gCnt, bCnt;
  250.     int        rHist[256], gHist[256], bHist[256];
  251.  
  252.     for (y = 0; y < input->height; y++) {
  253.         for (x = 0; x < input->width; x++) {
  254.             /*
  255.             **  compute histogram of (on-screen hunk of) n*n 
  256.             **    region centered plane
  257.             */
  258.  
  259.             rCnt = gCnt = bCnt = 0;
  260.             rVal = gVal = bVal = 0;
  261.             for (i = 0; i < XtNumber(rHist); i++)
  262.                 rHist[i] = gHist[i] = bHist[i] = 0;
  263.             
  264.             for (yy = y - AREA_2; yy < y + AREA_2; yy++) {
  265.                 if (yy < 0 || yy >= input->height)
  266.                     continue;
  267.                 for (xx = x - AREA_2; xx < x + AREA_2; xx++) {
  268.                     int        c, p;
  269.                     unsigned char    *rgb;
  270.  
  271.                     if (xx < 0 || xx >= input->width)
  272.                         continue;
  273.  
  274.                     rgb = ImagePixel(input, xx, yy);
  275.  
  276.                     if ((c= ++rHist[(p=rgb[0])/4]) > rCnt) {
  277.                         rVal = p;
  278.                         rCnt = c;
  279.                     }
  280.                     if ((c= ++gHist[(p=rgb[1])/4]) > gCnt) {
  281.                         gVal = p;
  282.                         gCnt = c;
  283.                     }
  284.                     if ((c= ++bHist[(p=rgb[2])/4]) > bCnt) {
  285.                         bVal = p;
  286.                         bCnt = c;
  287.                     }
  288.                 }
  289.             }
  290.  
  291.             *op++ = rVal;
  292.             *op++ = gVal;
  293.             *op++ = bVal;
  294.         }
  295.  
  296.         if (y % 16 == 0)
  297.             StateTimeStep();
  298.     }
  299.  
  300.     return output;
  301. }
  302.